﻿package com.sgcc.nfc.lock.presentation.region

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import com.sgcc.nfc.lock.R
import com.sgcc.nfc.lock.databinding.DialogRegionFormBinding
import com.sgcc.nfc.lock.databinding.FragmentRegionManagementBinding
import com.sgcc.nfc.lock.domain.model.Region
import com.sgcc.nfc.lock.domain.model.RegionLevel
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch

@AndroidEntryPoint
class RegionManagementFragment : Fragment() {

    private var _binding: FragmentRegionManagementBinding? = null
    private val binding get() = _binding!!
    private val viewModel: RegionManagementViewModel by viewModels()
    private lateinit var adapter: RegionAdapter
    private var currentDialog: AlertDialog? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentRegionManagementBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        setupRecycler()
        setupListeners()
        observeState()
    }

    private fun setupRecycler() {
        adapter = RegionAdapter(
            typeLabelProvider = ::resolveRegionTypeLabel,
            onToggleExpand = { item -> viewModel.toggleRegion(item.region.regionId) },
            onAddChild = { region -> showRegionFormDialog(parent = region, target = null) },
            onEdit = { region -> showRegionFormDialog(parent = null, target = region) },
            onDelete = { region -> confirmDelete(region) }
        )
        binding.regionRecycler.layoutManager = LinearLayoutManager(requireContext())
        binding.regionRecycler.adapter = adapter
    }

    private fun setupListeners() {
        binding.regionSwipeRefresh.setOnRefreshListener { viewModel.refresh() }
        binding.addRegionFab.setOnClickListener { showRegionFormDialog(parent = null, target = null) }
    }

    private fun observeState() {
        viewModel.uiState.observe(viewLifecycleOwner) { state ->
            binding.regionSwipeRefresh.isRefreshing = state.isLoading
            adapter.submitList(state.items)
            binding.emptyView.visibility = if (state.items.isEmpty() && !state.isLoading) View.VISIBLE else View.GONE
            state.error?.let { Snackbar.make(binding.root, it, Snackbar.LENGTH_LONG).show() }
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.events.collect { event ->
                    when (event) {
                        is RegionEvent.ShowMessage -> Snackbar.make(binding.root, event.message, Snackbar.LENGTH_LONG).show()
                        is RegionEvent.OperationSuccess -> {
                            val messageRes = when (event.type) {
                                RegionEvent.OperationType.CREATE -> R.string.region_create_success
                                RegionEvent.OperationType.UPDATE -> R.string.region_update_success
                                RegionEvent.OperationType.DELETE -> R.string.region_delete_success
                            }
                            Snackbar.make(binding.root, getString(messageRes), Snackbar.LENGTH_SHORT).show()
                        }
                        RegionEvent.FormSubmitted -> currentDialog?.dismiss()
                    }
                }
            }
        }
    }

    private fun showRegionFormDialog(parent: Region?, target: Region?) {
        val parentOptions = buildParentOptions()
        if (parentOptions.isEmpty()) {
            Snackbar.make(binding.root, getString(R.string.region_form_no_manageable_parent), Snackbar.LENGTH_LONG).show()
            return
        }
        val dialogBinding = DialogRegionFormBinding.inflate(layoutInflater)
        val isEdit = target != null
        dialogBinding.dialogTitle.setText(if (isEdit) R.string.region_form_title_edit else R.string.region_form_title_add)

        var selectedParentOption = run {
            val defaultParentId = when {
                isEdit -> target!!.parentId ?: 0L
                parent != null -> parent.regionId
                else -> viewModel.defaultParentId()
            }
            parentOptions.firstOrNull { it.id == defaultParentId } ?: parentOptions.first()
        }

        val parentLabels = parentOptions.map { it.displayLabel }
        dialogBinding.parentDropdown.setAdapter(
            ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, parentLabels)
        )
        dialogBinding.parentDropdown.setText(selectedParentOption.displayLabel, false)
        dialogBinding.parentDropdown.isEnabled = !isEdit && parentOptions.isNotEmpty()
        dialogBinding.parentLayout.isEnabled = !isEdit && parentOptions.isNotEmpty()
        dialogBinding.parentLayout.isEndIconVisible = !isEdit && parentOptions.size > 1
        dialogBinding.parentLayout.setEndIconOnClickListener {
            dialogBinding.parentDropdown.showDropDown()
        }
        dialogBinding.parentDropdown.setOnClickListener {
            if (!isEdit) dialogBinding.parentDropdown.showDropDown()
        }
        dialogBinding.parentDropdown.setOnFocusChangeListener { _, hasFocus ->
            if (!isEdit && hasFocus) dialogBinding.parentDropdown.showDropDown()
        }

        dialogBinding.nameInput.setText(target?.regionName.orEmpty())

        val levelAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, mutableListOf<String>())
        dialogBinding.typeDropdown.setAdapter(levelAdapter)
        dialogBinding.typeLayout.setEndIconOnClickListener {
            dialogBinding.typeDropdown.showDropDown()
        }
        dialogBinding.typeDropdown.setOnClickListener {
            if (!isEdit) dialogBinding.typeDropdown.showDropDown()
        }
        dialogBinding.typeDropdown.setOnFocusChangeListener { _, hasFocus ->
            if (!isEdit && hasFocus) dialogBinding.typeDropdown.showDropDown()
        }

        var selectedLevel: RegionLevel? = viewModel.regionLevel(target)
        var levelOptions = buildLevelOptions(selectedParentOption, selectedLevel, isEdit)
        fun applySelectedLevel(level: RegionLevel?) {
            selectedLevel = level
            val option = levelOptions.firstOrNull { it.level == level }
            val label = option?.label
            updateTypeField(dialogBinding, label, level != null)
            dialogBinding.saveButton.isEnabled = level != null
        }

        fun refreshLevelOptions(keepSelection: Boolean = false) {
            levelOptions = buildLevelOptions(
                parent = selectedParentOption,
                preferredLevel = when {
                    keepSelection -> selectedLevel
                    isEdit -> viewModel.regionLevel(target)
                    else -> null
                },
                isEdit = isEdit
            )
            levelAdapter.clear()
            levelAdapter.addAll(levelOptions.map { it.label })
            val initialLevel = when {
                isEdit -> viewModel.regionLevel(target)
                keepSelection && selectedLevel != null -> selectedLevel
                else -> levelOptions.firstOrNull()?.level
            }
            val initialOption = levelOptions.firstOrNull { it.level == initialLevel } ?: levelOptions.firstOrNull()
            dialogBinding.typeDropdown.setText(initialOption?.label.orEmpty(), false)
            dialogBinding.typeDropdown.isEnabled = !isEdit && levelOptions.isNotEmpty()
            dialogBinding.typeLayout.isEnabled = !isEdit && levelOptions.isNotEmpty()
            dialogBinding.typeLayout.isEndIconVisible = !isEdit && levelOptions.size > 1
            applySelectedLevel(initialOption?.level)
        }

        refreshLevelOptions()

        if (!isEdit) {
            dialogBinding.parentDropdown.setOnItemClickListener { _, _, position, _ ->
                selectedParentOption = parentOptions[position]
                refreshLevelOptions()
            }

            dialogBinding.typeDropdown.setOnItemClickListener { _, _, position, _ ->
                val option = levelOptions.getOrNull(position)
                dialogBinding.typeDropdown.setText(option?.label.orEmpty(), false)
                applySelectedLevel(option?.level)
            }
        }

        val dialog = MaterialAlertDialogBuilder(requireContext())
            .setView(dialogBinding.root)
            .create()
        currentDialog = dialog

        dialogBinding.cancelButton.setOnClickListener { dialog.dismiss() }
        dialogBinding.saveButton.setOnClickListener {
            val name = dialogBinding.nameInput.text?.toString()?.trim().orEmpty()
            if (name.isBlank()) {
                dialogBinding.nameLayout.error = getString(R.string.region_validation_name)
                return@setOnClickListener
            } else {
                dialogBinding.nameLayout.error = null
            }
            val level = selectedLevel
            if (level == null) {
                Snackbar.make(binding.root, getString(R.string.region_form_child_not_allowed), Snackbar.LENGTH_LONG).show()
                return@setOnClickListener
            }
            val parentId = selectedParentOption.id
            if (isEdit) {
                val region = target!!
                viewModel.updateRegion(region.regionId, name, level.value, parentId)
            } else {
                viewModel.createRegion(name, level.value, parentId)
            }
        }

        dialog.show()
    }

    private fun confirmDelete(region: Region) {
        MaterialAlertDialogBuilder(requireContext())
            .setTitle(R.string.region_delete_confirm)
            .setMessage(R.string.region_delete_confirm_message)
            .setNegativeButton(R.string.common_cancel, null)
            .setPositiveButton(R.string.common_delete) { _, _ ->
                viewModel.deleteRegion(region.regionId)
            }
            .show()
    }

    private fun resolveRegionTypeLabel(item: RegionListItem): String {
        val level = viewModel.regionLevel(item.region)
        if (level == RegionLevel.STATION) {
            val parentLevel = item.region.parentId?.let(viewModel::findRegionById)?.let(viewModel::regionLevel)
            if (parentLevel == RegionLevel.CITY) {
                return getString(R.string.region_type_center)
            }
        }
        return level?.let(::getRegionLevelLabel) ?: getString(R.string.region_type_station)
    }

    private fun getRegionLevelLabel(level: RegionLevel): String = when (level) {
        RegionLevel.HEADQUARTERS -> getString(R.string.region_type_headquarters)
        RegionLevel.PROVINCE -> getString(R.string.region_type_province)
        RegionLevel.CITY -> getString(R.string.region_type_city)
        RegionLevel.COUNTY -> getString(R.string.region_type_county)
        RegionLevel.STATION -> getString(R.string.region_type_station)
    }

    private fun updateTypeField(binding: DialogRegionFormBinding, label: String?, isEnabled: Boolean) {
        binding.typeDropdown.setText(label.orEmpty(), false)
        binding.typeLayout.helperText = if (!isEnabled) getString(R.string.region_form_child_not_allowed) else null
    }

    private fun buildParentOptions(): List<ParentOption> {
        val options = mutableListOf<ParentOption>()
        if (viewModel.canManageRoot()) {
            options += ParentOption(
                id = 0L,
                displayLabel = getString(R.string.region_form_parent_root),
                region = null,
                depth = 0
            )
        }
        fun append(regions: List<Region>, depth: Int) {
            for (region in regions) {
                if (!viewModel.canManageRegionId(region.regionId)) continue
                val label = buildString {
                    repeat(depth) { append("   ") }
                    append(region.regionName)
                }
                options += ParentOption(
                    id = region.regionId,
                    displayLabel = label,
                    region = region,
                    depth = depth
                )
                if (region.children.isNotEmpty()) {
                    append(region.children, depth + 1)
                }
            }
        }
        append(viewModel.currentTree(), 0)
        return options
    }

    override fun onDestroyView() {
        super.onDestroyView()
        currentDialog?.dismiss()
        currentDialog = null
        _binding = null
    }

    private data class ParentOption(
        val id: Long,
        val displayLabel: String,
        val region: Region?,
        val depth: Int
    )

    private data class LevelOption(
        val level: RegionLevel,
        val label: String
    )

    private fun buildLevelOptions(parent: ParentOption, preferredLevel: RegionLevel?, isEdit: Boolean): List<LevelOption> {
        val parentLevel = when {
            parent.id == 0L -> RegionLevel.HEADQUARTERS
            parent.region != null -> viewModel.regionLevel(parent.region)
            else -> null
        }
        val levels = when {
            isEdit && preferredLevel != null -> listOf(preferredLevel)
            else -> viewModel.childLevelsForParent(parent.id)
        }
        return levels.map { level ->
            val label = when {
                parentLevel == RegionLevel.CITY && level == RegionLevel.STATION -> getString(R.string.region_type_center)
                else -> getRegionLevelLabel(level)
            }
            LevelOption(level, label)
        }
    }
}







